package com.smartboot.plus.service;

import com.smartboot.plus.condition.ConditionGroup;
import com.smartboot.plus.condition.ConditionQ;
import com.smartboot.plus.exception.ServiceException;
import com.smartboot.plus.features.acl.MqttAclFeatures;
import com.smartboot.plus.ignite.IgniteCacheRegion;
import com.smartboot.plus.ignite.IgniteQueryExecutor;
import com.smartboot.plus.ignite.cache.MqttAclCache;
import com.smartboot.plus.ignite.listener.RefreshTopicBroadcast;
import com.smartboot.plus.utils.Func;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import tech.smartboot.feat.cloud.annotation.Autowired;
import tech.smartboot.feat.cloud.annotation.Bean;

import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

@Bean
public class MqttAclService implements IgniteQueryExecutor<MqttAclCache> {

    @Autowired
    private Ignite igniteInstance;

    @Autowired
    private MqttAclFeatures mqttAclFeatures;


    @Override
    public IgniteCache<String, MqttAclCache> getIgniteCache() {
        // 获取 ACL 缓存实例
        return igniteInstance.cache(IgniteCacheRegion.MQTT_ACL_CACHE.getCacheName());
    }

    /**
     * 提交或更新 ACL 数据
     * @param mqttAclCache 规则对象
     * @return 提交后对象的 ID
     */
    public boolean submit(MqttAclCache mqttAclCache) {
        // 校验规则合法性
        validateForm(mqttAclCache);

        // ID 为空则生成
        if (Func.isEmpty(mqttAclCache.getId())) {
            mqttAclCache.setId(Func.randomUUID());
        }

        // 查询是否已存在（用于判断是新增还是更新）
        ConditionGroup conditionGroup = new ConditionGroup()
                .add(new ConditionQ(MqttAclCache::getId, mqttAclCache.getId()));
        MqttAclCache existing = this.selectOne(conditionGroup, MqttAclCache.class);

        Timestamp now = new Timestamp(System.currentTimeMillis());

        if (existing == null) {

            mqttAclCache.getTopicEft().forEach(topicEft1 -> {
                String cleanedTopic = topicEft1.getTopic().trim().toLowerCase().replaceAll(" ","");
                topicEft1.setTopic(cleanedTopic);
            });
            //小写
            mqttAclCache.setTopicEft(mqttAclCache.getTopicEft());
            // 新增
            mqttAclCache.setCreatedAt(now);
            mqttAclCache.setUpdatedAt(now);
            getIgniteCache().put(mqttAclCache.getId(), mqttAclCache);
        } else {

            mqttAclCache.getTopicEft().forEach(topicEft1 -> {
                String cleanedTopic = topicEft1.getTopic().trim().toLowerCase().replaceAll(" ","");
                topicEft1.setTopic(cleanedTopic);
            });
            // 更新已有记录的特定字段
            existing.setTopicEft(mqttAclCache.getTopicEft());
            existing.setRemark(mqttAclCache.getRemark());
            existing.setUpdatedAt(now);
            getIgniteCache().put(existing.getId(), existing);
        }

        // 广播缓存更新事件
        igniteInstance.compute().broadcast(new RefreshTopicBroadcast(mqttAclCache.getUsername()));

        return true;
    }

    /**
     * 删除指定 ID 的规则
     * @param id 规则主键
     * @return 是否删除成功
     */
    public boolean removeId(String id) {
        if(Func.isEmpty(id)||Func.isBlank(id)){
            return false;
        }
        return this.removeById(id);
    }

    /**
     * 表单验证
     * 包括非空校验、重复校验、格式校验
     */
    private void validateForm(MqttAclCache mqttAclCache) {
        // ---------- 基础校验 ----------
        if (Func.isBlank(mqttAclCache.getUsername())) {
            throw new ServiceException("所属用户不能为空!");
        }

        if (Func.isEmpty(mqttAclCache.getTopicEft()) || mqttAclCache.getTopicEft().isEmpty()) {
            throw new ServiceException("Topic不能为空!");
        }

        Set<String> topicSet = new HashSet<>();
        for (MqttAclCache.TopicEft topic : mqttAclCache.getTopicEft()) {
            if (Func.isBlank(topic.getTopic())) {
                throw new ServiceException("Topic不能为空!");
            }
            if (Func.isBlank(topic.getAction())) {
                throw new ServiceException("动作不能为空!");
            }
            if (Func.isBlank(topic.getEffect())) {
                throw new ServiceException("效果不能为空!");
            }

            // 校验 Topic 格式
            if (!isValidMqttTopicFilter(topic.getTopic())) {
                throw new ServiceException(topic.getTopic() + " 格式不正确!");
            }

            // 检查重复 Topic
            if (!topicSet.add(topic.getTopic())) {
                throw new ServiceException("重复的 Topic: " + topic.getTopic());
            }
        }

        // 备注长度限制
        String remark = Optional.ofNullable(mqttAclCache.getRemark()).orElse("");
        if (remark.length() > 50) {
            throw new ServiceException("备注最大 50 个字符!");
        }

        // ---------- 用户名唯一性验证 ----------
        String id = Optional.ofNullable(mqttAclCache.getId()).orElse("");

        ConditionGroup conditionGroup = new ConditionGroup()
                .add(new ConditionQ(MqttAclCache::getUsername, mqttAclCache.getUsername()));

        // 排除自身 ID（用于更新时）
        if (Func.isNotEmpty(id)) {
            conditionGroup.add(new ConditionQ(MqttAclCache::getId, ConditionQ.NOT_EQ, id));
        }

        // 如果已有其他规则使用此用户名，报错
        MqttAclCache existing = this.selectOne(conditionGroup, MqttAclCache.class);
        if (existing != null) {
            throw new ServiceException("当前用户规则已存在!");
        }
    }

    /**
     * 校验 MQTT Topic Filter 是否合法
     * - '+' 必须是独立层级
     * - '#' 必须是最后一个层级且独立存在
     */
    public boolean isValidMqttTopicFilter(String topicFilter) {
        if (Func.isBlank(topicFilter)) {
            return false;
        }

        String[] levels = topicFilter.split("/");

        for (int i = 0; i < levels.length; i++) {
            String level = levels[i];

            if (level.contains("#")) {
                if (!level.equals("#") || i != levels.length - 1) {
                    return false;
                }
            }

            if (level.contains("+")) {
                if (!level.equals("+")) {
                    return false;
                }
            }
        }

        return true;
    }

}
